﻿#region Copyright(c) 2006 ZO, All right reserved.
// -----------------------------------------------------------------------------
// Copyright(c) 2006 ZO, All right reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//   1.  Redistribution of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//   2.  Redistribution in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//   3.  The name of the author may not be used to endorse or promote products
//       derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// -----------------------------------------------------------------------------
#endregion


#region Using directives

using System;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using ZO.SmartCore.Core;
using ZO.SmartCore.Net.Sockets.Properties;
using ArgumentException= ZO.SmartCore.Core.ArgumentException;

#endregion

namespace ZO.SmartCore.Net.Sockets
{
    /// <summary>
    /// Provides comprehensive Transmission Control Protocol support to send &amp; recieve data.
    /// </summary>
    public class TCPClient : BaseClientSocket
    {

        #region Constructors


        /// <summary>
        /// Initializes a new instance of the <see cref="TCPClient"/> class.
        /// </summary>
        public TCPClient() {}


        /// <summary>
        /// Initializes a new instance of the <see cref="TCPClient"/> class.
        /// </summary>
        /// <param name="encoding">The encoding.</param>
        public TCPClient(Encoding encoding) : base(encoding) { }
        #endregion

        #region Destructor

        #endregion

        #region Fields
        private Socket _Socket;

        private AsyncOperation connectOperation;
        private AsyncOperation disconnectOperation;
        private AsyncOperation receiveOperation;

        #endregion

        #region Events
        /// <summary>
        /// Occurs when the Send request completes. 
        /// </summary>
        /// <remarks>this event is raised even if any error occurs in that case 
        /// Exception Property is used to detect error info</remarks>
        public event EventHandler<SocketEventArgs> SendCompleted;

        /// <summary>
        /// Occurs when the Receive request completes. 
        /// </summary>
        /// <remarks>this event is raised even if any error occurs in that case 
        /// Exception Property is used to detect error info</remarks>
        public event EventHandler<SocketEventArgs> RecieveCompleted;

   

        #endregion

        #region Delgates

        private delegate void ConnectWorker();
        private delegate void DisconnectWorker();


        private delegate void ReceiveWorker();

        private delegate void ReceiveWorker2(byte[] buffer, int offset, int count, SocketFlags socketFlags);

        private delegate void SendWorker(AsyncOperation sendOperation, byte[] buffer, int offset, int count, SocketFlags socketFlags);

        #endregion


        #region Operators

        #endregion

        #region Properties
        /// <summary>
        /// Returns a reference to the <see cref="System.Net.Sockets.Socket"/> instance being used.
        /// </summary>
        /// <value></value>
        /// <remarks>
        /// The Socket used for the TCP connection is exposed through this property.
        /// It is not recommended to read or write to the TCP stream using the Socket object directly.
        /// </remarks>
        public override Socket Socket
        {
            get
            {
                return _Socket;
            }
            protected internal set
            {
                _Socket = value;
            }
        }

        /// <summary>
        /// Returns a Socket Stream that can be used for streaming operations on the socket.
        /// </summary>
        /// <exception cref="System.NotImplementedException">
        /// Not Implemented Yet
        /// </exception>
        public override SocketStream Stream
        {
            get
            {
                return new SocketStream(new TCPStream(this));
            }
 
        }

        #endregion

        #region Methods
        /// <summary>
        /// Connect to a host.
        /// </summary>
        public override void Connect()
        {

            try
            {
                if (!this.Address.IsResolved)
                {
                    base.OnResolving(EventArgs.Empty);
                    new ResolveDelegate(this.Address.Resolve).Invoke();
                    base.OnResolved(EventArgs.Empty);
                }


                //Create a TCP/IP socket.
                SocketPermission permission = new SocketPermission(NetworkAccess.Connect,
                    TransportType.Tcp, this.Address.Host, this.Address.Port);

                permission.Demand();

                this.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

                base.OnConnecting(EventArgs.Empty);

                new ConnectDelegate(this.Socket.Connect).Invoke(this.Address.Endpoint);

                base.OnConnectCompleted(EventArgs.Empty);

            }
            catch (SocketException ex)
            {
                base.OnError(new ExceptionEventArgs(ex));
            }

        }


   

        /// <summary>
        /// Send data to the server. 
        /// </summary>
        /// <param name="buffer">Source memory location for the data to send.</param>
        public void Send(byte[] buffer)
        {
            this.Send(buffer, 0, buffer.Length, SocketFlags.None);
        }

        /// <summary>
        /// Send data to the server. 
        /// </summary>
        /// <param name="buffer">Data to be decoded into bytes and sent.</param>
        [Description("Converts a string into a byte array and sends it.")]
        public void Send(string buffer)
        {
            byte[] byteArray = this.Encoding.GetBytes(buffer);
            this.Send(byteArray, 0, byteArray.Length, SocketFlags.None);
        }

        /// <summary>
        /// Send data asynchronously to the server. 
        /// </summary>
        /// <param name="buffer">Source memory location for the data to send.</param>
        public void SendAsync(byte[] buffer)
        {
            this.SendAsync(buffer, 0, buffer.Length, SocketFlags.None);
        }

        /// <summary>
        /// Send data asynchronously to the server. 
        /// </summary>
        /// <param name="buffer">Data to be decoded into bytes and sent.</param>
        [Description("Converts a string into a byte array and sends it.")]
        public void SendAsync(string buffer)
        {
            byte[] byteArray = this.Encoding.GetBytes(buffer);
            this.SendAsync(byteArray, 0, byteArray.Length, SocketFlags.None);
        }

        /// <summary>
        /// Send data asuncronously to the server, specifying a buffer, offset, count and SocketFlags value. 
        /// </summary>
        /// <param name="buffer">Source memory location for the data to send.</param>
        /// <param name="offset">Starting offset within buffer for sending.</param>
        /// <param name="count">Number of bytes to send.</param>
        /// <param name="socketFlags">A bitwise combination of special use sending parameters.</param>
        public virtual void SendAsync(byte[] buffer, int offset, int count, SocketFlags socketFlags)
        {
   

            AsyncOperation sendOperation = AsyncOperationManager.CreateOperation(null);


            new SendWorker(this.InternalSendAsync).BeginInvoke(sendOperation, buffer, offset, count, socketFlags, null, null);
        }

        /// <summary>
        /// Send data to the server, specifying a buffer, offset, count and SocketFlags value. 
        /// </summary>
        /// <param name="buffer">Source memory location for the data to send.</param>
        /// <param name="offset">Starting offset within buffer for sending.</param>
        /// <param name="count">Number of bytes to send.</param>
        /// <param name="socketFlags">A bitwise combination of special use sending parameters.</param>
        public virtual void Send(byte[] buffer, int offset, int count, SocketFlags socketFlags)
        {
            if (buffer == null)
            {
                this.OnError(new ExceptionEventArgs(new NullBufferException()));
                return;
            }

            if (offset < 0)
            {
                this.OnError(new ExceptionEventArgs(new NonnegativeNumberRequiredException("offset")));
                return;
            }

            if (count < 0)
            {
                this.OnError(new ExceptionEventArgs(new NonnegativeNumberRequiredException("count")));
                return;
            }

            if ((buffer.Length - offset) < count)
            {
                this.OnError(new ExceptionEventArgs(new ArgumentException(Resources.Argument_InvalidOffLen)));
                return;
            }

            if (this.State != SocketState.Connected | !this.Connected)
            {
                this.OnError(new ExceptionEventArgs(new SocketException(Resources.SocketNotConnected)));
                return;
            }

            try
            {
                new AsyncSocketReadWrite(this.Socket.Send).Invoke(buffer, offset, count, socketFlags);
            }
            catch (SocketException ex)
            {
                this.OnError(new ExceptionEventArgs(ex));
                return;
            }
        }

        /// <summary>
        /// Raises the <see cref="SendCompleted"/> event.
        /// </summary>
        /// <param name="e">The <see cref="T:SmartCore.Net.Sockets.SocketEventArgs"/> instance containing the event data.</param>
        protected virtual void OnSendCompleted(SocketEventArgs e)
        {
            if (SendCompleted != null)
            {
                SendCompleted(this, e);
            }
        } // OnSend


        /// <summary>
        /// Raises the <see cref="RecieveCompleted"/> event.
        /// </summary>
        /// <param name="e">The <see cref="T:SmartCore.Net.Sockets.SocketEventArgs"/> instance containing the event data.</param>
        protected virtual void OnRecieveCompleted(SocketEventArgs e)
        {

            if (RecieveCompleted != null)
            {
                RecieveCompleted(this, e);
            }
        } // OnSend

   

        /// <overloads>
        /// Receive data from the host. 
        /// </overloads>
        /// <summary>
        /// Receive data from the host. 
        /// </summary>
        /// <param name="buffer">Destination memory location to store received data.</param>
        public int Receive(byte[] buffer)
        {
            return this.Receive(buffer, 0, buffer.Length, SocketFlags.None);
        }


        /// <summary>
        /// Receive data asynchronously from the host. 
        /// </summary>
        /// <param name="buffer">Destination memory location to store received data.</param>
        public void ReceiveAsync(byte[] buffer)
        {
            this.ReceiveAsync(buffer, 0, buffer.Length, SocketFlags.None);
        }


        /// <summary>
        /// Receive data asynchronously from the host till available bytes is not equal 0 &amp; raise Recieve Event. 
        /// </summary>
        public virtual void Receive()
        {
            byte[] buffer = new byte[this.ReceiveBufferSize]; ;
            MemoryStream ms = new MemoryStream();

            try
            {


                int num;
                while (this.Available > 0)
                {
                    num = new AsyncSocketReadWrite(this.Socket.Receive).Invoke(buffer, 0, 
                        this.ReceiveBufferSize, SocketFlags.None);

                   Thread.Sleep(0);
                    ms.Write(buffer, 0, num);

                }
                this.OnRecieveCompleted(new SocketEventArgs(new Segment(ms.ToArray(), 0, (int)ms.Length, SocketFlags.None)));


            }
            catch (SocketException ex)
            {
                this.OnRecieveCompleted(new SocketEventArgs(new Segment(ms.ToArray(), 0, (int)ms.Length, SocketFlags.None), ex));
                this.OnError(new ExceptionEventArgs(ex));
            }
        }

        /// <summary>
        /// Receive data asynchronously from the host till available bytes is not equal 0 &amp; raise Recieve Event. 
        /// </summary>
        public virtual void ReceiveAsync()
        {
            // Create an AsyncOperation for taskId.
            if (receiveOperation != null)
            {
                //Recieving Data Currently;
                return;
            }

            receiveOperation = AsyncOperationManager.CreateOperation(this);


            new ReceiveWorker(this.InternalReceiveAsync).BeginInvoke(null, null);
        }


        private void InternalReceiveAsync()
        {
            byte[] buffer = new byte[this.ReceiveBufferSize]; ;
            MemoryStream ms = new MemoryStream();

            try
            {
                if (receiveOperation == null)
                {
                    return;
                }
                
                int num;
                while (this.Available > 0)
                {
                    num = new AsyncSocketReadWrite(this.Socket.Receive).Invoke(buffer, 0,
                        this.ReceiveBufferSize, SocketFlags.None);

                    ms.Write(buffer, 0, num);

                }


                receiveOperation.PostOperationCompleted(delegate { this.OnRecieveCompleted(new SocketEventArgs(new Segment(ms.ToArray(), 0, (int)ms.Length, SocketFlags.None))); }, null);
                
                // Yield the rest of this time slice.
                Thread.Sleep(0);


                receiveOperation = null;

            }
            catch (Exception ex)
            {
                if (receiveOperation != null)
                {
                    receiveOperation.Post(delegate { this.OnRecieveCompleted(new SocketEventArgs(new Segment(ms.ToArray(), 0, (int)ms.Length, SocketFlags.None), ex)); }, null);

                    // Yield the rest of this time slice.
                    Thread.Sleep(0);

                    receiveOperation.PostOperationCompleted(delegate { this.OnError(new ExceptionEventArgs(ex)); }, null);

                    // Yield the rest of this time slice.
                    Thread.Sleep(0);

                    receiveOperation = null;
                }

            }
        }


            /// <summary>
        /// Receive data from the host, specifying a buffer, offset, count and SocketFlags value. 
        /// </summary>
        /// <param name="buffer">Destination memory location to store received data.</param>
        /// <param name="offset">Starting offset within buffer for filling.</param>
        /// <param name="count">Maximum number of bytes to receive.</param>
        /// <param name="socketFlags">A bitwise combination of special use receiving parameters.</param>
        public virtual void ReceiveAsync(byte[] buffer, int offset, int count, SocketFlags socketFlags)
        {
            // Create an AsyncOperation for taskId.
            if (receiveOperation != null)
            {
                receiveOperation.OperationCompleted();
                receiveOperation = null;
            }

            receiveOperation = AsyncOperationManager.CreateOperation(null);


            new ReceiveWorker2(this.InternalReceiveAsync).BeginInvoke(buffer, offset, count, socketFlags, null, null);
        }

        /// <summary>
        /// Receive data from the host, specifying a buffer, offset, count and SocketFlags value. 
        /// </summary>
        /// <param name="buffer">Destination memory location to store received data.</param>
        /// <param name="offset">Starting offset within buffer for filling.</param>
        /// <param name="count">Maximum number of bytes to receive.</param>
        /// <param name="socketFlags">A bitwise combination of special use receiving parameters.</param>
        public virtual int Receive(byte[] buffer, int offset, int count, SocketFlags socketFlags)
        {
            if (buffer == null)
            {
                this.OnError(new ExceptionEventArgs(new NullBufferException()));
                return -1;
            }

            if (offset < 0)
            {
                this.OnError(new ExceptionEventArgs(new NonnegativeNumberRequiredException("offset")));
                return -1;
            }

            if (count < 0)
            {
                this.OnError(new ExceptionEventArgs(new NonnegativeNumberRequiredException("count")));
                return -1;
            }

            if ((buffer.Length - offset) < count)
            {
                this.OnError(new ExceptionEventArgs(new ArgumentException(Resources.Argument_InvalidOffLen)));
                return -1;
            }

            if (this.State != SocketState.Connected | !this.Connected)
            {
                this.OnError(new ExceptionEventArgs(new SocketException(Resources.SocketNotConnected)));
                return -1;
            }

            try
            {
                int num = new AsyncSocketReadWrite(this.Socket.Receive).Invoke(buffer, offset, count, socketFlags);

                return num;
            }
            catch (SocketException ex)
            {
                this.OnError(new ExceptionEventArgs(ex));
                return -1;

            }
        }




        /// <summary>
        /// Internals the receive async.
        /// </summary>
        /// <param name="buffer">The buffer.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="count">The count.</param>
        /// <param name="socketFlags">The socket flags.</param>
        private void InternalReceiveAsync(byte[] buffer, int offset, int count, SocketFlags socketFlags)
        {
            if (receiveOperation == null)
            {
                return;
            }


            if (buffer == null)
            {
                receiveOperation.Post(delegate { this.OnError(new ExceptionEventArgs(new NullBufferException())); }, null);

                receiveOperation.OperationCompleted();

                receiveOperation = null;

                return;
            }

            if (offset < 0)
            {
                receiveOperation.Post(delegate { this.OnError(new ExceptionEventArgs(new NonnegativeNumberRequiredException("offset"))); }, null);
                receiveOperation.OperationCompleted();

                // Yield the rest of this time slice.
               Thread.Sleep(0);
                receiveOperation = null;

                return;
            }

            if (count < 0)
            {
                receiveOperation.Post(delegate { this.OnError(new ExceptionEventArgs(new NonnegativeNumberRequiredException("count"))); }, null);
                receiveOperation.OperationCompleted();

                // Yield the rest of this time slice.
               Thread.Sleep(0);
                receiveOperation = null;

                return;
            }

            if ((buffer.Length - offset) < count)
            {
                receiveOperation.Post(delegate { this.OnError(new ExceptionEventArgs(new ArgumentException(Resources.Argument_InvalidOffLen))); }, null);
                receiveOperation.OperationCompleted();

                // Yield the rest of this time slice.
               Thread.Sleep(0);
                receiveOperation = null;

                return;
            }

            if (this.State != SocketState.Connected | !this.Connected)
            {
                receiveOperation.Post(delegate { this.OnError(new ExceptionEventArgs(new SocketException(Resources.SocketNotConnected))); }, null);
                receiveOperation.OperationCompleted();

                receiveOperation = null;

                return;
            }

            try
            {
                int num = new AsyncSocketReadWrite(this.Socket.Receive).Invoke(buffer, offset, count, socketFlags);

                receiveOperation.PostOperationCompleted(delegate { this.OnRecieveCompleted(new SocketEventArgs(new Segment(buffer, offset, count, socketFlags, num))); }, null);

                // Yield the rest of this time slice.
               Thread.Sleep(0);

                receiveOperation = null;

            }
            catch (SocketException ex)
            {
                if (receiveOperation != null)
                {
                    receiveOperation.Post(delegate { this.OnRecieveCompleted(new SocketEventArgs(new Segment(buffer, offset, count, socketFlags), ex)); }, null);
                    // Yield the rest of this time slice.
                   Thread.Sleep(0);

                    receiveOperation.PostOperationCompleted(delegate { this.OnError(new ExceptionEventArgs(ex)); }, null);
                    // Yield the rest of this time slice.
                   Thread.Sleep(0);

                    receiveOperation = null;
                }

            }
        }


    


        /// <summary>
        /// Begins an asynchronous request for a remote host connection.
        /// </summary>
        public override void ConnectAsync()
        {
            // Create an AsyncOperation for taskId.
            if (connectOperation != null)
            {
                connectOperation.OperationCompleted();
                connectOperation = null;
            }

            connectOperation = AsyncOperationManager.CreateOperation(null);


            new ConnectWorker(this.InternalConnectAsync).BeginInvoke(null, null);

        }

        /// <summary>
        /// Cancel an asynchronous request for a remote host connection.
        /// </summary>
        public virtual void ConnectAsyncCancel()
        {
            // Create an AsyncOperation for taskId.
            if (connectOperation != null)
            {
                connectOperation.OperationCompleted();
                connectOperation = null;
            }
        }

        /// <summary>
        /// Begins an asynchronous request for a remote host disconnection.
        /// </summary>
        public override void DisconnectAsync()
        {
            // Create an AsyncOperation for taskId.
            if (disconnectOperation != null)
            {
                disconnectOperation.OperationCompleted();
                disconnectOperation = null;
            }

            disconnectOperation = AsyncOperationManager.CreateOperation(null);


            new DisconnectWorker(this.InternalDisconnectAsync).BeginInvoke(null, null);

        }


        /// <summary>
        /// Begins an asynchronous request for a remote host connection.
        /// </summary>
        private void InternalDisconnectAsync()
        {
            try
            {
                if (disconnectOperation == null)
                {
                    return;
                }




                disconnectOperation.Post(delegate { this.OnDisconnecting(EventArgs.Empty); }, null);

                // Yield the rest of this time slice.
                Thread.Sleep(0);


                new DisconnectDelegate(this.Disconnect).Invoke();


                disconnectOperation.PostOperationCompleted(delegate { this.OnDisconnectCompleted(EventArgs.Empty); }, null);

                // Yield the rest of this time slice.
                Thread.Sleep(0);

                disconnectOperation = null;

            }
            catch (Exception ex)
            {
                if (disconnectOperation != null)
                {
                    disconnectOperation.PostOperationCompleted(delegate { this.OnError(new ExceptionEventArgs(ex)); }, null);

                    disconnectOperation = null;
                }

            }
        }



        /// <summary>
        /// Cancel an asynchronous request to receive data.
        /// </summary>
        public virtual void ReceieveAsyncCancel()
        {
            // Create an AsyncOperation for taskId.
            if (receiveOperation != null)
            {
                receiveOperation.OperationCompleted();
                receiveOperation = null;
            }
        }

        /// <summary>
        /// Begins an asynchronous request for a remote host connection.
        /// </summary>
        private void InternalConnectAsync()
        {
            try
            {
                if (connectOperation == null)
                {
                    return;
                }




                connectOperation.Post(delegate { this.OnResolving(EventArgs.Empty); }, null);

                // Yield the rest of this time slice.
               Thread.Sleep(0);


                new ResolveDelegate(this.Address.Resolve).Invoke();

                connectOperation.Post(delegate { this.OnResolved(EventArgs.Empty); }, null);

                // Yield the rest of this time slice.
               Thread.Sleep(0);

                //Create a TCP/IP socket.
                SocketPermission permission = new SocketPermission(NetworkAccess.Connect,
                    TransportType.Tcp, this.Address.Host, this.Address.Port);

                permission.Demand();

                this.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);


                connectOperation.Post(delegate { this.OnConnecting(EventArgs.Empty); }, null);

                // Yield the rest of this time slice.
                Thread.Sleep(0);

                new ConnectDelegate(this.Socket.Connect).Invoke(this.Address.Endpoint);


                connectOperation.PostOperationCompleted(delegate { this.OnConnectCompleted(EventArgs.Empty); }, null);

                // Yield the rest of this time slice.
                Thread.Sleep(0);

                connectOperation = null;

            }
            catch (Exception ex)
            {
                if (connectOperation != null)
                {
                    connectOperation.PostOperationCompleted(delegate { this.OnError(new ExceptionEventArgs(ex)); }, null);

                    connectOperation = null;
                }
                
            }
        }


        private void InternalSendAsync(AsyncOperation sendOperation, byte[] buffer, int offset, int count, SocketFlags socketFlags)
        {
            if (sendOperation == null)
            {
                return;
            }


            if (buffer == null)
            {
                sendOperation.Post(delegate { this.OnError(new ExceptionEventArgs(new NullBufferException())); }, null);

                sendOperation.OperationCompleted();


                return;
            }

            if (offset < 0)
            {
                sendOperation.Post(delegate { this.OnError(new ExceptionEventArgs(new NonnegativeNumberRequiredException("offset"))); }, null);
                sendOperation.OperationCompleted();


                return;
            }

            if (count < 0)
            {
                sendOperation.Post(delegate { this.OnError(new ExceptionEventArgs(new NonnegativeNumberRequiredException("count"))); }, null);
                sendOperation.OperationCompleted();


                return;
            }

            if ((buffer.Length - offset) < count)
            {
                sendOperation.Post(delegate { this.OnError(new ExceptionEventArgs(new ArgumentException(Resources.Argument_InvalidOffLen))); }, null);
                sendOperation.OperationCompleted();


                return;
            }

            if (this.State != SocketState.Connected | !this.Connected)
            {
                sendOperation.Post(delegate { this.OnError(new ExceptionEventArgs(new SocketException(Resources.SocketNotConnected))); }, null);
                sendOperation.OperationCompleted();


                return;
            }

            try
            {
                int num = new AsyncSocketReadWrite(this.Socket.Send).Invoke(buffer, offset, count, socketFlags);

                sendOperation.PostOperationCompleted(delegate { this.OnSendCompleted(new SocketEventArgs(new Segment(buffer, offset, count, socketFlags, num))); }, null);

                // Yield the rest of this time slice.
               Thread.Sleep(0);

                sendOperation = null;

            }
            catch (SocketException ex)
            {
                if (sendOperation != null)
                {
                    sendOperation.Post(delegate { this.OnSendCompleted(new SocketEventArgs(new Segment(buffer, offset, count, socketFlags), ex)); }, null);
                    // Yield the rest of this time slice.
                   Thread.Sleep(0);

                    sendOperation.PostOperationCompleted(delegate { this.OnError(new ExceptionEventArgs(ex)); }, null);
                    // Yield the rest of this time slice.
                   Thread.Sleep(0);

                }

            }
        }
        #endregion
     

   
    }
}
